package com.arpa.ntocc.common.security.aspect;

import com.arpa.ntocc.common.common.constant.StrConsts;
import com.arpa.ntocc.common.common.exception.AuthorizeTokenException;
import com.arpa.ntocc.common.common.exception.PermissionException;
import com.arpa.ntocc.common.common.exception.RoleException;
import com.arpa.ntocc.common.common.exception.ServiceException;
import com.arpa.ntocc.common.common.util.RedisUtil;
import com.arpa.ntocc.common.security.annotation.NoRepeat;
import lombok.extern.log4j.Log4j2;
import org.apache.oltu.oauth2.rs.request.OAuthAccessResourceRequest;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

/**
 * 重复提交切片处理类
 * @Author liuyj
 * @Date 2020-03-03 17:04:37
 */
@Component
@Aspect
@Log4j2
public class NoRepeatAop {

    /**
     * 定义有一个切入点，范围为ntocc包下的类
     */
    @Pointcut("execution(public * com.arpa..*.*(..))")
    public void annotationPointCut() {
    }

    /**
     * 切面before
     * @param joinPoint
     * @throws Exception
     */
    @Before("annotationPointCut()")
    public void before(JoinPoint joinPoint) throws Exception {
        try {
            MethodSignature sign =  (MethodSignature)joinPoint.getSignature();
            Method method = sign.getMethod();
            NoRepeat annotation = method.getAnnotation(NoRepeat.class);
            if(annotation!=null){
                int time = annotation.time();
                //判断是否重复提交
                if(isRepeat(time)){
                    throw new ServiceException("请勿重复提交");
                }
            }
        }catch(AuthorizeTokenException authorizeTokenException){
            throw authorizeTokenException;
        }catch(RoleException roleException){
            throw roleException;
        }catch(PermissionException permissionExeption){
            throw permissionExeption;
        }catch (Exception e){
            log.error(StrConsts.CATCH_MESSAGE,e);
            throw e;
        }
    }

    /**
     * 是否重复提交
     * @return
     */
    private boolean isRepeat(int time) {
        boolean flag=false;
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            //构建OAuth资源请求
            OAuthAccessResourceRequest oauthRequest = new OAuthAccessResourceRequest(request);
            //获取Access Token
            String accessToken = oauthRequest.getAccessToken();
            String uri = request.getRequestURI();
            String key = accessToken+"_"+uri;
            //验证token合法性
            if (RedisUtil.get(key)!=null) {
                flag=true;
            }else{
                RedisUtil.setPexpire(key,"1",time);
            }
        } catch (Exception e) {
            log.error(StrConsts.CATCH_MESSAGE,e);
        }
        return flag;
    }

}
